package classes;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import enums.Category;
import enums.MeasuringSystem;

public class Unit {
	private String label;

    private Category category;

    private MeasuringSystem system;
    
    private Boolean ref;
    
    private HashMap<Unit, Conversion> convert;
    
    public Unit() {
    	this.convert = new HashMap<Unit, Conversion>();
    	this.ref = false;
    }

    /* Getters and Setters */
	public String getLabel() {
		return label;
	}

	public void setLabel(String label) {
		this.label = label;
	}

	public Category getCategory() {
		return category;
	}

	public void setCategory(Category category) {
		this.category = category;
	}

	public MeasuringSystem getSystem() {
		return system;
	}

	public void setSystem(MeasuringSystem system) {
		this.system = system;
	}

	public Boolean getRef() {
		return ref;
	}

	public void setRef(Boolean ref) {
		this.ref = ref;
	}

	public HashMap<Unit, Conversion> getConvert() {
		return convert;
	}

	public void setConvert(Unit unit, double fact, double ope) {
		this.convert.put(unit, new Conversion(fact, ope));
	}    

	public double convert(float value, Unit theUnit) {
		double result = 0;
		
		if (this.category == theUnit.getCategory()){
			double factor = 0; 
			double ope = 0; 
			
			if (this.getSystem() != theUnit.getSystem()){
				/** Temperature management **/
				if ((this.category == Category.TEMPERATURE) && (this.system == MeasuringSystem.BRITISH)){ 
					factor = this.convert.get(theUnit).getFactor();
					ope = this.convert.get(theUnit).getOperand();
					result = (value - ope) * factor;
				} else if ((this.category == Category.TEMPERATURE) && (this.system == MeasuringSystem.METRIC)){
					factor = this.convert.get(theUnit).getFactor();
					ope = this.convert.get(theUnit).getOperand();
					result = value * factor + ope;
				} 
				
				/** management intersystem conversion **/
				else {
					// Conversion between systems : cm -> feet example
					HashMap<Unit,Conversion> unit = this.convert;
					Iterator it = unit.entrySet().iterator();
					while (it.hasNext()) {
						Map.Entry ent = (Map.Entry) it.next();
						Unit key = (Unit) ent.getKey();
				 
						if (key.ref){ // if theUnit is reference
							factor = this.convert.get(key).getFactor();
							ope = this.convert.get(key).getOperand();
							result = value * factor + ope; // example : cm -> km 
							
							Iterator it2 = key.convert.entrySet().iterator();
							while(it2.hasNext()){
								Map.Entry ent2 = (Map.Entry) it2.next();
								Unit key2 = (Unit) ent2.getKey();
								
								if (key2.ref){
									factor = key.convert.get(key2).getFactor();
									ope = key.convert.get(key2).getOperand();
									result = result * factor + ope; // km -> mile example
									
									factor = key2.convert.get(theUnit).getFactor();
									ope = key2.convert.get(theUnit).getOperand();
									result = result * factor + ope; // mile -> feet example
									
								} //end if key2 ref
							} //end while it2
						} // end if key ref
					} //end while it 
				} //end if else temperature
			} //end if different systems
			
			/** Management intrasystem conversion **/
			else { 
				factor = this.convert.get(theUnit).getFactor();
				ope = this.convert.get(theUnit).getOperand();
				result = value * factor + ope;
			}
			
		} else {
			System.out.println("Conversion impossible : les cat�gories "+this.category+" et "+theUnit.getCategory()+" sont incompatibles.");
		}
		
    	return result;
    }



}
